﻿using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Wy.JiZhangSoft.ZhangDans.Dtos;

namespace Wy.JiZhangSoft.ZhangDans
{
    [Authorize]
    public class ZhangDanAppService : JiZhangSoftAppService
    {
        private readonly IRepository<ZhangDan> _zhangDans;
        private readonly IRepository<LeiJiZhiChuStatistics> _dayChangeStatistics;
        private readonly IRepository<MonthLatelyZhiChuStatistic> _monthLatelyZhiChuStatistics;

        public ZhangDanAppService(IRepository<ZhangDan> zhangDans,
            IRepository<LeiJiZhiChuStatistics> dayChangeStatistics,
            IRepository<MonthLatelyZhiChuStatistic> monthLatelyZhiChuStatistics)
        {
            this._zhangDans = zhangDans;
            this._dayChangeStatistics = dayChangeStatistics;
            this._monthLatelyZhiChuStatistics = monthLatelyZhiChuStatistics;
        }

        public Task Add(ZhangDanAddDto dto)
        {
            ZhangDan entity = new ZhangDan(GuidGenerator.Create());
            entity = ObjectMapper.Map(dto, entity);

            if (entity.Date <= DateTime.Now.AddDays(-(ZhangDanConst.StatisticMaxDay-1)))
            {
                _dayChangeStatistics.DeleteAsync(x => x.UserId == CurrentUser.Id);
            }
            return _zhangDans.InsertAsync(entity);
        }

        public async Task<ZhangDanGetDto> Get(Guid id)
        {
            var entity = await _zhangDans.SingleOrDefaultAsync(x => x.Id == id);
            return ObjectMapper.Map<ZhangDan, ZhangDanGetDto>(entity);
        }

        public async Task Delete(Guid id)
        {
            var entity = await _zhangDans.SingleOrDefaultAsync(x => x.Id == id);
            if (CurrentUser.Id == entity.CreatorId)
                await _zhangDans.DeleteAsync(x => x.Id == id);
            else
                throw new BusinessException("不能删除别人的记录");
        }

        public PagedResultDto<ZhangDanGetDto> GetPageList(ZhangDanGetParameter input)
        {
            var query = _zhangDans.Where(x=>x.CreatorId==CurrentUser.Id).WhereIf(!string.IsNullOrEmpty(input.KeyWords), x => x.Name.Contains(input.KeyWords) || x.Classified.Contains(input.KeyWords) || x.Desc.Contains(input.KeyWords));
            query = query.OrderByDescending(x => x.Date);
            var entites = query.PageBy(input.SkipCount, input.MaxResultCount).ToList();
            var dtos = ObjectMapper.Map<List<ZhangDan>, List<ZhangDanGetDto>>(entites);
            long count = query.LongCount();
            //throw new BusinessException("HELLO");
            return new PagedResultDto<ZhangDanGetDto>(count, dtos);
        }
        public async Task Update(Guid id, ZhangDanUpdateDto item)
        {
            ZhangDan zd = await _zhangDans.SingleOrDefaultAsync(o => o.Id == id);
            zd = ObjectMapper.Map(item, zd);
            if (item.Date <= DateTime.Now.AddDays(-(ZhangDanConst.StatisticMaxDay - 1)) && item.Price != zd.Price)
            {
                await _dayChangeStatistics.DeleteAsync(x => x.UserId == CurrentUser.Id);
            }
            await _zhangDans.UpdateAsync(zd);
        }

        /// <summary>
        /// 获取累计支出统计数据
        /// </summary>
        /// <returns></returns>
        public LeiJiZhiChuStatisticGetDto[] GetLeiJiZhiChuStatistic()
        {
            var dayChangeStatistics = _dayChangeStatistics.Where(x=>x.UserId==CurrentUser.Id).OrderBy(x => x.Day).Take(365 * 3).OrderBy(x=>x.Day).ToArray();
            return ObjectMapper.Map<LeiJiZhiChuStatistics[], LeiJiZhiChuStatisticGetDto[]>(dayChangeStatistics);
        }

        /// <summary>
        /// 获取最近多少条月支出统计数据
        /// </summary>
        /// <param name="count"></param>
        public MonthStatisticGetDto[] GetMonthZhiChuStatistic(int count)
        {
            var entites = _monthLatelyZhiChuStatistics.Where(x=>x.UserId==CurrentUser.Id)
                .OrderBy(x => x.CreationTime)
                .Take(count).ToArray();
            return ObjectMapper.Map<MonthLatelyZhiChuStatistic[], MonthStatisticGetDto[]>(entites);
        }

        public object GetYearZhiChuStatistic()
        {
            var entites = _monthLatelyZhiChuStatistics.Where(x => x.UserId == CurrentUser.Id)
                .ToArray()
                .GroupBy(x => x.Year)
                .Select(x => new { 
                    Year = x.Key+"年",
                    Money = x.Sum(x=>x.Price)
                })
                .OrderBy(x => x.Year);
            return entites;
        }

        /// <summary>
        /// 获取统计集合
        /// </summary>
        /// <returns></returns>
        public StatisticSetGetDto GetStatisticSet()
        {
            DateTime now = DateTime.Now;
            var leiJiZhiChuStatistics = _dayChangeStatistics.Where(x => x.UserId == CurrentUser.Id);
            var latelyMonthStatistic = leiJiZhiChuStatistics.Where(x =>x.Day >= now.AddMonths(-1).AddDays(-ZhangDanConst.StatisticMaxDay) && x.Day  <= now);
            // 近一月总消费
            var latelyMonthStatisticTotal = latelyMonthStatistic.Sum(x=>x.JinRiXiaoFei);
            // 近一月平均消费
            var latelyMonthStatisticAvg = latelyMonthStatisticTotal==0?0: latelyMonthStatistic.Average(x => x.JinRiXiaoFei);
            // 近一年总消费
            var latelyYearStatistic = leiJiZhiChuStatistics.Where(x => x.Day  >= now.AddYears(-1) && x.Day  <= now);
            var latelyYearStatisticTotal =  latelyYearStatistic.Sum(x => x.JinRiXiaoFei);
            // 近一年平均消费
            var latelyYearStatisticAvg = latelyYearStatisticTotal == 0 ? 0 : latelyYearStatistic.Average(x => x.JinRiXiaoFei);
            // 总平均消费
            var totalStisticAvg = leiJiZhiChuStatistics.Any(x => x.JinRiXiaoFei > 0) ? leiJiZhiChuStatistics.Average(x => x.JinRiXiaoFei) : 0;
            var dto = new StatisticSetGetDto
            {
                LatelyMonthStatisticAvg = Math.Round(latelyMonthStatisticAvg, 4),
                LatelyMonthStatisticTotal = latelyMonthStatisticTotal,
                LatelyYearStatisticAvg = Math.Round(latelyYearStatisticAvg, 4),
                LatelyYearStatisticTotal = latelyYearStatisticTotal,
                TotalStisticAvg = Math.Round(totalStisticAvg, 4)
            };
            return dto;
        }
    }
}
